package com.meida.module.arc.provider.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.OpenHelper;
import com.meida.common.security.OpenUser;
import com.meida.common.utils.ApiAssert;
import com.meida.module.arc.client.entity.ArcField;
import com.meida.module.arc.client.entity.ArcFieldSys;
import com.meida.module.arc.client.entity.ArcInfo;
import com.meida.module.arc.client.enums.ArchiveEnumInteger;
import com.meida.module.arc.client.utils.ArcUtils;
import com.meida.module.arc.provider.mapper.ArcFieldSysMapper;
import com.meida.module.arc.provider.service.ArcCategoryService;
import com.meida.module.arc.provider.service.ArcFieldService;
import com.meida.module.arc.provider.service.ArcFieldSysService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


/**
 * 系统字段表接口实现类
 *
 * @author flyme
 * @date 2021-11-22
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ArcFieldSysServiceImpl extends BaseServiceImpl<ArcFieldSysMapper, ArcFieldSys> implements ArcFieldSysService {

    @Autowired
    private ArcCategoryService arcCategoryService;

    @Autowired
    private ArcFieldService arcFieldService;

    private boolean checkEnName(String enName,Long exclusionId){
        CriteriaQuery<ArcFieldSys> query = new CriteriaQuery<ArcFieldSys>(ArcFieldSys.class);
        query.lambda().eq(ArcFieldSys::getEnName,enName);
        if(FlymeUtils.isNotEmpty(exclusionId)){
            query.lambda().ne(ArcFieldSys::getFieldSysId,exclusionId);
        }
        Long count = this.baseMapper.selectCount(query);
        return count==null||count==0?true:false;
    }

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, ArcFieldSys afs, EntityMap extra) {
        OpenUser user = OpenHelper.getUser();
        ApiAssert.isNotEmpty("类型字段不能为空",afs.getType());
        if(!ArchiveEnumInteger.IS_ADMIN.getCode().equals(user.getSuperAdmin())){
            return ResultBody.failed("非管理员无法添加系统字段");
        }
        if(FlymeUtils.isEmpty(afs.getSeq())){
            CriteriaQuery<ArcFieldSys> query = new CriteriaQuery<ArcFieldSys>(ArcFieldSys.class);
            query.eq("type", afs.getType());
            query.orderByDesc("seq");
            query.limit(1);
            ArcFieldSys field = this.baseMapper.selectOne(query);
            if (FlymeUtils.isEmpty(field)) {
                afs.setSeq(0);
            } else {
                afs.setSeq(field.getSeq() + 1);
            }
        }
        afs.setEnName(ArcUtils.replaceBlank(afs.getEnName()));
        String enKey = "enName:" + afs.getEnName();
        Object o = redisUtils.get(enKey);
        if (ObjectUtil.isNotNull(o)) {
            return ResultBody.failed("英文名称不能重复");
        }
        if (!checkEnName(afs.getEnName(), null)) {
            return ResultBody.failed("英文名称不能重复");
        }
        redisUtils.set("enName:" + afs.getEnName(), afs.getEnName());

        //TODO 已添加的门类增加门类字段
        addCategoryField(afs);
        return ResultBody.ok();
    }


    private void addCategoryField(ArcFieldSys item){
        if(ArchiveEnumInteger.IS_BIZ_FIELD.getCode().equals(item.getType())) {
            /*LambdaQueryWrapper<ArcCategory> arcCategoryLambdaQueryWrapper =
                    new LambdaQueryWrapper<>();
            arcCategoryLambdaQueryWrapper.ne(ArcCategory::getType, CategoryTypeEnum.CATEGORY_TYPE_0.getCode());
            List<ArcCategory> categories = this.arcCategoryService.list(arcCategoryLambdaQueryWrapper);*/
            Field[] declaredFields = ArcInfo.class.getDeclaredFields();
            List<String> fieldsName = Arrays.stream(declaredFields).map(f -> {
                return f.getName();
            }).collect(Collectors.toList());
            List<ArcField> fields = new ArrayList<>();

            LambdaQueryWrapper<ArcField> arcFieldLambdaQueryWrapper1 = new QueryWrapper<ArcField>().lambda().ne(ArcField::getFieldName, item.getEnName()).inSql(ArcField::getCategoryId, "select arc_category.categoryId from arc_category where type <>0");
            //校验是否已有该字段
            LambdaQueryWrapper<ArcField> arcFieldLambdaQueryWrapper =
                    new LambdaQueryWrapper<>();
            arcFieldLambdaQueryWrapper.eq(ArcField::getFieldName, item.getEnName());
            List<ArcField> list1 = arcFieldService.list(arcFieldLambdaQueryWrapper);
            if (CollUtil.isNotEmpty(list1)) {
                arcFieldLambdaQueryWrapper1.notIn(ArcField::getCategoryId, list1.stream().map(ArcField::getCategoryId).distinct().collect(Collectors.toList()));
            }

            List<ArcField> list = arcFieldService.list(arcFieldLambdaQueryWrapper1);

            if (CollUtil.isEmpty(list)) {
                return;
            } else {
                List<Long> collect = list.stream().map(ArcField::getCategoryId).distinct().collect(Collectors.toList());

                for (Long categoryId : collect) {

                    ArcField field = new ArcField();
                if(fieldsName.contains(item.getEnName())){
                    field.setIsBlob(ArchiveEnumInteger.IS_FALSE.getCode());
                }else{
                    field.setIsBlob(ArchiveEnumInteger.IS_TRUE.getCode());
                }
                field.setFieldId(IdWorker.getId());
                    field.setDeleted(0);
                    field.setCategoryId(categoryId);
                    field.setFieldName(item.getEnName());
                field.setFieldCnName(item.getCnName());
                field.setDataType(item.getDataType());
                field.setDefaultValue(item.getDefaultValue());
                field.setColumnLength(item.getLength());
                field.setInType(item.getDataType().intValue() == 2 ? 2 : 1);
                field.setInSeq(30);
                field.setInLength(250);
                field.setInMaxLength(250);
                field.setInMinLength(0);
                field.setInLine(0);
                field.setInShow(0);
                field.setInRequire(0);
                field.setInSearch(0);
                field.setInAutoGen(0);
                field.setInAutoPlus(0);
                field.setInInherit(0);
                field.setInAutoZero(0);
                field.setInZeroNum(0);
                field.setInNoRepeat(0);
                field.setOutSeq(30);
                field.setOutLength(250);
                field.setOutFormat(2);
                field.setOutIsShow(0);
                field.setOutIsOrder(0);
                field.setOutOrderSeq(0);
                    field.setOutOrderType("ASC");
                    field.setIsArcNum(0);
                    field.setArcSeq(0);
                    field.setSeq(30);
                    field.setIsSystem(ArchiveEnumInteger.IS_SYSTEM.getCode());
                    fields.add(field);
                }
                if (fields.size() > 0) {
                    //this.arcFieldService.saveBatch(fields);
                    this.mutiInsert(fields);
                }
            }
        }
    }

    @Override
    public ResultBody beforeDelete(CriteriaDelete<ArcFieldSys> cd) {
        OpenUser user = OpenHelper.getUser();
        if (!ArchiveEnumInteger.IS_ADMIN.getCode().equals(user.getSuperAdmin())) {
            return ResultBody.failed("非管理员无法删除系统字段");
        }
        //系统字段无法删除
        if (checkSysField(cd.getIdValue())) {
            ApiAssert.failure("系统类型字段无法删除");
        }
        ArcFieldSys obj = this.getById(cd.getIdValue());
        String enKey = "enName:" + obj.getEnName();
        Object o = redisUtils.get(enKey);
        if (ObjectUtil.isNotNull(o)) {
            redisUtils.del(enKey);
        }
        return ResultBody.ok();
    }

    private boolean checkSysField(Long arcFieldSysId){
        ArcFieldSys sys = this.baseMapper.selectById(arcFieldSysId);
        if(sys.getType()==1){
            return true;
        }else{
            return false;
        }
    }

    @Override
    public ResultBody beforeEdit(CriteriaUpdate<ArcFieldSys> cu, ArcFieldSys t, EntityMap extra) {
        ApiAssert.isNotEmpty("业务主键不能为空",t.getFieldSysId());
        //系统字段无法编辑
        if(checkSysField(cu.getIdValue())){
            ApiAssert.failure("系统类型字段无法编辑");
        }
        OpenUser user = OpenHelper.getUser();
        if(!ArchiveEnumInteger.IS_ADMIN.getCode().equals(user.getSuperAdmin())){
            return ResultBody.failed("非管理员无法修改系统字段");
        }

//        Integer type = null;
//        if(FlymeUtils.isEmpty(t.getType())){
//            ArcFieldSys fieldSys = this.baseMapper.selectById(t.getFieldSysId());
//            type = fieldSys.getType();
//        }else{
//            type = t.getType();
//        }

        if(!checkEnName(t.getEnName(),t.getFieldSysId())){
            return ResultBody.failed("英文名称不能重复");
        }
        return ResultBody.ok();
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<ArcFieldSys> cq, ArcFieldSys afs, EntityMap requestMap) {
      cq.orderByDesc("afs.createTime");
      return ResultBody.ok();
    }
}
